package per.hnvcam.hedge.algebra.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import per.hnvcam.common.OrderedSet;
import per.hnvcam.common.impl.OrderedSetImpl;
import per.hnvcam.hedge.algebra.Hedge2AlgebraDefinition;
import per.hnvcam.hedge.algebra.Hedge2Quantifier;

import java.util.HashMap;
import java.util.Map;

@Service("Hedge2Quantifier")
public class Hedge2QuantifierImpl implements Hedge2Quantifier {
   private Map<String, Double> cachedQuantifyValues;

   public Hedge2QuantifierImpl() {
      cachedQuantifyValues = new HashMap<String, Double>();
   }

   @Autowired
   @Qualifier("Hedge2AlgebraDefinition")
   private Hedge2AlgebraDefinition hedge2AlgebraDefinition;

   private double getOmegaValue(String compound) {
      String [] terms = compound.split(" ");
      if (terms.length < 2) {
         throw new IllegalArgumentException("The input term \"" + compound + "\" is invalid.");
      }
      double value = 0.5 * (((hedge2AlgebraDefinition.getBeta() - hedge2AlgebraDefinition.getAlpha()) *
         hedge2AlgebraDefinition.getSign(compound) *
         hedge2AlgebraDefinition.getSign(hedge2AlgebraDefinition.getPositiveH() + " " + compound)) + 1);
      return value;
   }

   @Override
   public double getQuantifyValue(String compound) {
      if (cachedQuantifyValues.containsKey(compound)) {
         return cachedQuantifyValues.get(compound);
      }

      double value = 0.0;

      if (hedge2AlgebraDefinition.getNeutral().equals(compound)) {
         value = hedge2AlgebraDefinition.getFunctionMeterValue(hedge2AlgebraDefinition.getNegativeG());
         cachedQuantifyValues.put(hedge2AlgebraDefinition.getNeutral(), value);
         return value;
      }

      if (hedge2AlgebraDefinition.getNegativeG().equals(compound)) {
         value = hedge2AlgebraDefinition.getBeta() *
            hedge2AlgebraDefinition.getFunctionMeterValue(hedge2AlgebraDefinition.getNegativeG());
         cachedQuantifyValues.put(hedge2AlgebraDefinition.getNegativeG(), value);
         return value;
      }

      if (hedge2AlgebraDefinition.getPositiveG().equals(compound)) {
         value = hedge2AlgebraDefinition.getFunctionMeterValue(hedge2AlgebraDefinition.getNegativeG()) +
            hedge2AlgebraDefinition.getAlpha() *
               hedge2AlgebraDefinition.getFunctionMeterValue(hedge2AlgebraDefinition.getPositiveG());
         cachedQuantifyValues.put(hedge2AlgebraDefinition.getPositiveG(), value);
         return value;
      }

      int idx = compound.indexOf(" ");
      if (idx < 0) {
         throw new IllegalArgumentException("The input term \"" + compound + "\" is invalid.");
      }

      String hedge = compound.substring(0, idx);
      String tail = compound.substring(idx + 1, compound.length());

      double sigma = hedge2AlgebraDefinition.getFunctionMeterValue(compound);

      double omega = getOmegaValue(compound) *
         hedge2AlgebraDefinition.getFunctionMeterValue(hedge) * hedge2AlgebraDefinition.getFunctionMeterValue(tail);

      value = getQuantifyValue(tail) + (hedge2AlgebraDefinition.getSign(compound) *
         (sigma - omega));

      cachedQuantifyValues.put(compound, value);

      return value;
   }

   @Override
   public OrderedSet<Double> getQuantifyValues(OrderedSet<String> set) {
      OrderedSet<Double> result = new OrderedSetImpl<Double>();
      for (String term : set) {
         result.add(getQuantifyValue(term));
      }
      return result;
   }

   @Override
   public OrderedSet<Double> getFuzzinessInterval(int degree) {
      OrderedSet<String> similarityInterval = hedge2AlgebraDefinition.getAllTermsOfLength(degree + 1);
      OrderedSet<Double> ranges = new OrderedSetImpl<Double>();
      for (int i = 0; i < similarityInterval.size(); i++) {
         String term = similarityInterval.getAt(i);
         if (i != (similarityInterval.size() / 2 - 1)) {
            ranges.add(getQuantifyValue(term));
         }
      }
      return ranges;
   }
}
